#!/usr/bin/env python3
# filename: views.py

from os import path
from uuid import uuid4
import datetime
import pdb

from flask import (
        flash,
        render_template,
        Blueprint,
        redirect,
        url_for,
        abort)

from flask_principal import (
        Permission,
        UserNeed)

from sqlalchemy import func
from flask_login import login_required, current_user

from hzsaiblog.models import db, User, Post, Tag, Comment, posts_tag
from hzsaiblog.forms import CommentForm, PostForm

from hzsaiblog.extensions import poster_permission, admin_permission


""" Notice:
    the db.session.query(Model) does Not have the .first_or_404()
    the Objects have
"""


blog_blueprint = Blueprint(
        'blog',
        __name__,
        # path.pardit ==> ..
        template_folder=path.join(path.pardir, 'templates', 'blog'),
        # prefix of Route URL
        url_prefix='/blog')


def sidebar_data():
    """Sidebar data Prepartion"""

    # Get post of recent.
    recent = db.session.query(Post).order_by(
            Post.publish_date.desc()
            ).limit(5).all()

    # Get the tags and sort by count of posts.
    """Tag, count"""
    top_tags = db.session.query(
            Tag, func.count(posts_tag.c.post_id).label('total')
            ).join(
                posts_tag
            ).group_by(Tag).order_by('total asc').limit(5).all()

    return recent, top_tags


@blog_blueprint.route('/')
@blog_blueprint.route('/<int:page>')
def home(page=1):
    """View function for home page."""

    posts = Post.query.order_by(
        Post.publish_date.desc()
    ).paginate(page, 10)

    recent, top_tags = sidebar_data()

    return render_template(
            'home.html',
            posts=posts,
            recent=recent,
            top_tags=top_tags)


@blog_blueprint.route('/post/<string:post_id>', methods=['GET', 'POST'])
def post(post_id):
    """View function for post page."""

    # Form object: `Comment`
    form = CommentForm()
    username = current_user.username if current_user.is_authenticated else "anony"

    if form.validate_on_submit():
        if current_user.is_authenticated:
            new_comment = Comment(id=str(uuid4()), name=form.name.data)
            new_comment.date = datetime.datetime.now()
            new_comment.text = form.text.data
            new_comment.post_id = post_id
            db.session.add(new_comment)
            db.session.commit()
        else:
            flash('Please login to comment!', category='success')
            return redirect(url_for('blog.post', post_id=post_id))
    # Be Notice Before
    # post = db.session.query(Post).get_or_404(post_id)
    post = Post.query.get_or_404(post_id)
    tags = post.tags
    # TODO: paginate 
    # comments = post.comment.order_by(Comment.date.desc()).paginate(page, 10)

    comments = post.comment.order_by(Comment.date.desc()).all()
    recent, top_tags = sidebar_data()

    # print("Tags: ", tags)
    # return render_template(
    #         'post.html',
    #         post=post,
    #         tags=tags,
    #         comments=comments,
    #         form=form,
    #         recent=recent,
    #         top_tags=top_tags)

    return render_template(
            'post.html',
            post=post,
            tags = tags,
            comments=comments,
            form=form,
            username=username)


@blog_blueprint.route('/tag/<string:tag_name>')
def tag(tag_name):
    """View function for tag page"""

    # tag = db.session.filter_by(name=tag_name).first_or_404()
    tag = Tag.query.get_or_404(tag_name)
    # BUG the db.session.query(Model) haven't got the first_or_404()
    # tag = db.session.query(Tag).filter_by(name=tag_name).first_or_404()
    posts = tag.posts.order_by(Post.publish_date.desc()).all()
    recent, top_tags = sidebar_data()

    return render_template(
            'tag.html',
            tag=tag,
            posts=posts,
            recent=recent,
            top_tags=top_tags)


@blog_blueprint.route('/user/<string:username>')
def user(username):
    """View function for user page."""

    # user = db.session.query(User).filter_by(username=username).first_or_404()
    user = User.query.filter_by(username=username).first_or_404()
    posts = user.posts.order_by(Post.publish_date.desc()).all()
    recent, top_tags = sidebar_data()

    return render_template(
            'user.html',
            user=user,
            posts=posts,
            recent=recent,
            top_tags=top_tags)


@blog_blueprint.route('/new', methods=['GET', 'POST'])
@login_required
def new_post():
    """New post."""

    form = PostForm()

    if form.validate_on_submit():
        print("he")
        new_post = Post(id=str(uuid4()), title=form.title.data)
        new_post.text = form.text.data
        new_post.publish_date = datetime.datetime.now()
        new_post.users = current_user
        new_tag = Tag.query.filter_by(name=form.latest_tag.data).first()
        if new_tag is None:
            new_tag = Tag(id=str(uuid4()), name=form.latest_tag.data)
            new_post.tags.append(new_tag)
            # new_tag
            db.session.add(new_tag)
        else:
            new_post.tags.append(new_tag)

        db.session.add(new_post)
        db.session.commit()

        return redirect(url_for('blog.home'))

    return render_template('new_post.html', form=form)


@blog_blueprint.route('/edit/<string:id>', methods=['POST', 'GET'])
@login_required
@poster_permission.require(http_exception=403)
def edit_post(id):
    """View function for edit_post."""

    post = Post.query.get_or_404(id)

    # pdb.set_trace()
    # loggin ensure
    if not current_user:
        return redirect(url_for('main.login'))

    # only the poster can edit the post
    # if current_user != post.users:
    #     return redirect(url_for('blog.post', post_id=id))

    permission = Permission(UserNeed(post.users.id))
    if permission.can() or admin_permission.can():

        # only the poster can edit the post
        # if current_user != post.users:
        #     return redirect(url_for('blog.post', post_id=id))

        form = PostForm()

        if form.validate_on_submit():
            post.title = form.title.data
            post.text = form.text.data
            post.publish_date = datetime.datetime.now()
            allTags = Tag.query.all()
            # new_tags = [y for x in form.latest_tag.data.split(sep=',) for y in x.split()]
            new_tags = [x.strip() for x in form.latest_tag.data.split(sep=',')]
            tag_tmp = None
            for new_tag in new_tags:
                found = False
                for allTag in allTags:
                    if new_tag == allTag.name:
                        # old Tag
                        found = True
                        tag_tmp = allTag
                        break
                if not found:
                    tag_tmp = Tag(id=str(uuid4()), name=new_tag)
                    db.session.add(tag_tmp)
                post.tags.append(tag_tmp)

            # commit
            db.session.add(post)
            db.session.commit()
            return redirect(url_for('blog.home'))
    else:
        abort(403)

    # anoymous views
    tags = [x.name for x in post.tags]
    form.latest_tag.data = ",".join(tags)
    form.title.data = post.title
    form.text.data = post.text
    return render_template('edit_post.html', form=form, post=post)
